package com.dgut.courses_selecting_sys.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dgut.courses_selecting_sys.constants.CourseStatus;
import com.dgut.courses_selecting_sys.constants.RabbitMqKey;
import com.dgut.courses_selecting_sys.constants.RedisKey;
import com.dgut.courses_selecting_sys.constants.UserConstants;
import com.dgut.courses_selecting_sys.entity.Course;
import com.dgut.courses_selecting_sys.entity.User;
import com.dgut.courses_selecting_sys.entity.UserCourse;
import com.dgut.courses_selecting_sys.entity.UserRole;
import com.dgut.courses_selecting_sys.enums.UserRoleEnum;
import com.dgut.courses_selecting_sys.mapper.CourseMapper;
import com.dgut.courses_selecting_sys.mapper.DeptMapper;
import com.dgut.courses_selecting_sys.mapper.UserCourseMapper;
import com.dgut.courses_selecting_sys.service.ICourseService;
import com.dgut.courses_selecting_sys.service.IUserRoleService;
import com.dgut.courses_selecting_sys.utils.RedisUtil;
import com.dgut.courses_selecting_sys.utils.ShiroUtils;
import com.dgut.courses_selecting_sys.utils.core.StrFormatter;
import com.dgut.courses_selecting_sys.utils.core.StringUtils;
import com.dgut.courses_selecting_sys.vo.CourseVo;
import com.dgut.courses_selecting_sys.vo.PageVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author yuec
 * @since 2020-08-14
 */
@Slf4j
@Service
public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course> implements ICourseService {

    @Autowired
    CourseMapper courseMapper;
    @Autowired
    DeptMapper deptMapper;
    @Autowired
    UserCourseMapper userCourseMapper;
    @Autowired
    RedisUtil redisUtil;
    @Autowired
    StringRedisTemplate redisTemplate;
    @Autowired
    IUserRoleService userRoleService;
    @Autowired
    RabbitTemplate rabbitTemplate;

    final static String notes_prefix = "Choose:notes:*";//这个*一定要加，否则无法模糊查询
    final static String start_prefix = "Choose:start:*";//这个*一定要加，否则无法模糊查询
    final static String end_prefix = "Choose:end:*";//这个*一定要加，否则无法模糊查询

    /**
     * 查询课程历史
     * 做redis缓存
     * TODO
     *
     * @param courseVo
     * @return
     */
    @Override
    public PageVo<Course> getDataByCourseVo(CourseVo courseVo) throws Exception {
        QueryWrapper<Course> queryWrapper = new QueryWrapper<>();
        queryWrapper.like(StringUtils.isNotEmpty(courseVo.getCourseName()), "course_name", courseVo.getCourseName());
        queryWrapper.ge(StringUtils.isNotNull(courseVo.getStartDate()), "gmt_create", courseVo.getStartDate())
                .le(StringUtils.isNotNull(courseVo.getEndDate()), "gmt_create", courseVo.getEndDate());
        queryWrapper.eq(StringUtils.isNotNull(courseVo.getDeptId()), "dept_id", courseVo.getDeptId());
        if (userRoleService.getDataByUserId(ShiroUtils.getUserId()).getRoleId().equals(UserRoleEnum.STUDENT.getRoleId())){
                queryWrapper.and(
                        wrapper -> wrapper.eq("status", CourseStatus.PASS).or()
                                .eq("status", CourseStatus.CHOICE).or()
                                .eq("status", CourseStatus.ING)
                );
        }else{
            queryWrapper.eq(StringUtils.isNotNull(courseVo.getStatus()),"status",courseVo.getStatus());
        }
        queryWrapper.orderByDesc("gmt_create");
        IPage<Course> page = new Page<>(courseVo.getPageNumber(), courseVo.getPageSize());
        courseMapper.selectPage(page, queryWrapper);
        PageVo<Course> pages = new PageVo<>();
        for (Course course : page.getRecords()) {
            course.setTimetable(StrFormatter.toTimetable(course.getTimetable()));
        }
        pages.setRows(page.getRecords());
        pages.setTotal(page.getTotal());
        return pages;
    }

    /**
     * 根据用户
     *
     * @param user
     * @return
     */
    @Override
    public List<Course> courseForChoose(User user) throws Exception {
        String ancestors = deptMapper.selectById(user.getDeptId()).getAncestors();
        String[] strList = ancestors.split(",");
//        if (strList.length>2){
//            Object arrayStr = redisUtil.get(RedisKey.COURSE_FOR_CHOOSE_BY_DEPT_ID + strList[2]);
//            if (arrayStr!=null){
//                return JSONObject.parseArray(arrayStr.toString(), Course.class);
//            }
//        }
        QueryWrapper<Course> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("status", CourseStatus.CHOICE).orderByAsc("course_name");
        if (user.getUserId() != UserConstants.ADMIN) {
            List list = new ArrayList();
            list.add(user.getDeptId());
            for (int i = 0; i < strList.length; i++) {
                list.add(Integer.valueOf(strList[i]));
            }
            queryWrapper.in("dept_id", list);
        }
        List<Course> courselist = courseMapper.selectList(queryWrapper);
        for (Course course : courselist) {
            course.setTimetable(StrFormatter.toTimetable(course.getTimetable()));
        }

        return courselist;
    }

    @Override
    public List checkUserCourseForChoose(User user) {
        Map map = new HashMap<>();
        map.put("user_id", user.getUserId());
        List<UserCourse> ucList = userCourseMapper.selectByMap(map);
        List result = new ArrayList<Long>();
        for (UserCourse list : ucList) {
            result.add(list.getCourseId());
        }
        return result;
    }

    
    @Override
    public boolean reviewAndConfirm(long start, long end, long now, List<Integer> list) {
        Course course = new Course();
        course.setStatus(String.valueOf(CourseStatus.PASS));
        try {
            CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
            MessagePostProcessor messageToChoice = message -> {
                MessageProperties messageProperties = message.getMessageProperties();
//          设置编码
                messageProperties.setContentEncoding("utf-8");
//          设置延时时间
                long wait = start - now;
                messageProperties.setExpiration(String.valueOf(wait));
                return message;
            };
            MessagePostProcessor messageToIng = message -> {
                MessageProperties messageProperties = message.getMessageProperties();
//          设置编码
                messageProperties.setContentEncoding("utf-8");
//          设置延时时间
                long wait = end - now;
                messageProperties.setExpiration(String.valueOf(wait));
                return message;
            };

            for (int n : list) {
                String message = JSON.toJSONString(n);
                course.setCourseId((long) n);
                course.setStartChooseTime(new Date(start));
                course.setEndChooseTime(new Date(end));
                courseMapper.updateById(course);
                rabbitTemplate.convertAndSend(RabbitMqKey.MY_NORMAL_EXCHANGE, RabbitMqKey.COURSE_CHOICE_ROUTING_KEY, message,messageToChoice,correlationData);
                rabbitTemplate.convertAndSend(RabbitMqKey.MY_NORMAL_EXCHANGE, RabbitMqKey.COURSE_ING_ROUTING_KEY, message,messageToIng,correlationData);
            }
            return true;
        } catch (Exception e) {
            log.error("审核课程::出现错误");
            return false;
        }
    }

/*

    @CacheEvict(value = RedisKey.COURSE_FOR_CHOOSE_BY_DEPT_ID, allEntries = true, condition = "#result==1")
    public int checkCourseStatus() {
        */
/**
         * return
         * 0:没有改变状态
         * 1:发生改变
         *//*

        Course course = new Course();
        Set<String> start_keys = redisTemplate.keys(start_prefix);
        Set<String> end_keys = redisTemplate.keys(end_prefix);
        if (start_keys.size() == end_keys.size()) {
            */
/**
             * 课程开选结束
             *//*

            Set<String> notes_keys = redisTemplate.keys(notes_prefix);
            if (notes_keys.size() == end_keys.size()) {
                return 0;
            }
            end_keys.forEach(n -> {
                        n.replace("end", "notes");
                    }
            );
            notes_keys.removeAll(end_keys);
            course.setStatus(String.valueOf(CourseStatus.ING));
            notes_keys.forEach(
                    n -> {
                        String[] str = n.split(":");
                        long courseId = Long.valueOf(str[2]);
                        course.setCourseId(courseId);
                        courseMapper.updateById(course);
                        redisUtil.del(n);
                        log.warn("课程开选结束::课程编号->" + course.getCourseId());
                    }
            );
            return 1;
        }

        */
/**
         * 课程开选
         *//*

        start_keys.forEach(n -> {
            n.replace("start", "end");
        });
        end_keys.removeAll(start_keys);
        course.setStatus(String.valueOf(CourseStatus.CHOICE));
        end_keys.forEach(
                n -> {
                    String[] str = n.split(":");
                    long courseId = Long.valueOf(str[2]);
                    course.setCourseId(courseId);
                    courseMapper.updateById(course);
                    log.warn("课程开选::课程编号->" + course.getCourseId());
                }
        );
        return 1;

    }

*/

}
